<template>
	<div ref="container">
		<div style="position: absolute; z-index: 10" class="flex-center w100 h100" v-show="loading">
			<dv-decoration :scale="2">
				<span class="fw" style="font-size: 30px"> {{ percentComplete }}% </span>
			</dv-decoration>
		</div>
		<my-compass :keyType="keyType" />
	</div>
</template>

<script setup name="tunnelling3d">
import myLabel from '@c/common/my-label.vue'
import { DBUtil } from '@u/indexedDB'
import { useResizeObserver, THREE, GLTFloaderFn, rendererFn, labelRendererFn, cameraFn, compassRotate, CSS3DSprite, keyType } from '@u/threeMinx'

let container = shallowRef(null), // 模型渲染的Demo节点
	renderer, //  WebGLRenderer渲染器
	scene, // 场景
	camera, // 相机
	loading = ref(false),
	percentComplete = ref(0),
	labelRenderer,
	cameraRender

// 组件宽高
let width, height
useResizeObserver(container, (entries) => {
	width = entries[0].contentRect.width
	height = entries[0].contentRect.height
	camera.aspect = width / height
	camera.updateProjectionMatrix()
	renderer.setSize(width, height)
	labelRenderer.setSize(width, height)
})
// 初始化生命周期
onMounted(() => {
	loading.value = true
	init()
})
onBeforeUnmount(() => {
	cancelAnimationFrame(requestAnimationFrameIndex)
	// 释放显存
	renderer?.dispose()
	// 释放内存
	container = null
	scene = null
})

function init() {
	// 场景
	scene = new THREE.Scene()
	// 相机
	camera = new THREE.PerspectiveCamera(45, width / height, 1, 2000)
	camera.position.set(-8, 3, 10)
	camera.lookAt(0, 3, -8)
	// 相机旋转移动
	cameraRender = cameraFn(camera)
	scene.add(camera)
	// label渲染器
	labelRenderer = labelRendererFn(container)
	// 渲染器
	renderer = rendererFn(container)
	// 灯光
	lights()
	// 加载器
	loaderFn()
}

let objects = [],
	labelObj = new THREE.Group()
function loaderFn() {
	new DBUtil().get(`${import.meta.env.VITE_APP_BASE_BASE || '/'}model/瓦斯抽放系统.glb`).then((blob) => {
		let url = URL.createObjectURL(blob)
		GLTFloaderFn.load(
			url,
			(object) => {
				loading.value = false
				scene.add(object.scene)
				scene.add(labelObj)
				objects = object.scene.getObjectByName('墙001').children
				// 渲染器
				render()
			},
			(xhr) => {
				if (xhr.lengthComputable) percentComplete.value = Math.round((xhr.loaded / xhr.total) * 100, 2)
			}
		)
	})
}

// 添加label逻辑
const props = defineProps({
		data: {
			type: Object,
			required: true
		}
	}),
	data1 = computed(() => {
		let data = []
		props.data?.pumpData?.forEach((item) => {
			data.push({
				name: item.pumpName,
				list: [
					{
						title: '运行状态',
						val: item.pumpState == 1 ? '正常' : '停止'
					},
					{
						title: '出口压力',
						val: item.pumpPressure,
						suffix: 'KPa'
					}
				]
			})
		})
		return data
	}),
	data2 = computed(() => {
		let data = []
		props.data?.pumpData?.forEach((item) => {
			data.push({
				name: item.pumpName,
				list: [
					{
						title: '阀门开度',
						val: item.pumpValve,
						suffix: '%'
					}
				]
			})
		})
		return data
	}),
	data3 = computed(() => {
		let data = []
		props.data?.pipelineData?.forEach((item) => {
			if (item.pipelineType == '1') {
				data.push({
					name: '高压管道',
					list: [
						{
							title: '管道压力',
							val: item.pipelinePressure,
							suffix: 'KPa'
						},
						{
							title: '管道流量',
							val: item.pipelineFlow,
							suffix: 'm³/min'
						},
						{
							title: '管道瓦斯浓度',
							val: item.pipelineGas,
							suffix: '%'
						}
					]
				})
			}
		})
		return data[0]
	})

watch(
	() => props.data,
	() => {
		labelFn()
	}
)

function labelFn() {
	labelObj.clear()
	data1.value.forEach((item, i) => {
		CSS3DSpriteFn(
			createApp(myLabel, {
				data: item,
				callBack: function () {}
			}).mount(document.createElement('div')).$el,
			[-7.7 + i * 5.5, 0.7, 1]
		)
	})
	data2.value.forEach((item, i) => {
		CSS3DSpriteFn(
			createApp(myLabel, {
				data: item,
				callBack: function () {}
			}).mount(document.createElement('div')).$el,
			[-6.5 + i * 5, 3.3, -1]
		)
	})
	if (data3.value) {
		CSS3DSpriteFn(
			createApp(myLabel, {
				data: data3.value,
				callBack: function () {}
			}).mount(document.createElement('div')).$el,
			[-5, 5, 0]
		)
	}
}

function CSS3DSpriteFn(dom, position) {
	const pointLabel = new CSS3DSprite(dom)
	pointLabel.position.set(...position)
	pointLabel.scale.set(0.012, 0.012, 0.012)
	labelObj.add(pointLabel)
}

/**
 * 灯光
 */
function lights() {
	// 自然光
	scene.add(new THREE.AmbientLight('#d6c9c9'), 0.2)
	let light2 = new THREE.DirectionalLight('#ffffff', 0.5)
	light2.position.set(-50, 50, 50)
	scene.add(light2)
}

// 渲染逻辑
let requestAnimationFrameIndex
function render() {
	// 漫游
	keyType.value = cameraRender(objects)
	compassRotate(camera)
	// label渲染器
	labelRenderer?.render(scene, camera)
	renderer?.render(scene, camera)
	requestAnimationFrameIndex = requestAnimationFrame(render)
}
</script>
